﻿//-----------------------------------------------------------------------------
// <copyright file="CommonDialogImplementer.cs" company="William E. Kempf">
//     Copyright (c) William E. Kempf.
// </copyright>
//-----------------------------------------------------------------------------

namespace Onyx.Windows
{
    using System;
    using System.Windows;
    using Microsoft.Win32;
    using Onyx.Reflection;

    /// <summary>
    /// Provides an abstract class that provides standard implementation of
    /// <see cref="ICommonDialog"/> by deferring to an instance of
    /// <see cref="Microsoft.Win32.CommonDialog"/>.
    /// </summary>
    /// <typeparam name="T">The <see cref="CommonDialog"/> to defer to.</typeparam>
    public abstract class CommonDialogImplementer<T> : ICommonDialog
        where T : CommonDialog
    {
        /// <summary>
        /// The <see cref="CommonDialog"/> to defer to.
        /// </summary>
        private readonly T dialog;

        /// <summary>
        /// The owner <see cref="Window"/>.
        /// </summary>
        private readonly Window owner;

        /// <summary>
        /// Initializes a new instance of the <see cref="CommonDialogImplementer{T}"/> class.
        /// </summary>
        /// <param name="owner">The owner <see cref="Window"/>.</param>
        /// <param name="dialog">The <see cref="Microsoft.Win32.CommonDialog"/>
        /// to use in the implementation.</param>
        protected CommonDialogImplementer(Window owner, T dialog)
        {
            if (dialog == null)
            {
                throw new ArgumentNullException(Reflect.GetField(() => dialog).Name);
            }

            this.owner = owner;
            this.dialog = dialog;
        }

        /// <summary>
        /// Gets or sets an object associated with the dialog. This provides
        /// the ability to attach an arbitrary object to the dialog.
        /// </summary>
        /// <value>A <see cref="System.Object"/> that is attached or associated
        /// with a dialog.</value>
        public object Tag
        {
            get
            {
                return this.Dialog.Tag;
            }

            set
            {
                this.Dialog.Tag = value;
            }
        }

        /// <summary>
        /// Gets the wrapped dialog used in the implementation.
        /// </summary>
        /// <value>The dialog.</value>
        protected T Dialog
        {
            get { return this.dialog; }
        }

        /// <summary>
        /// Displays a common dialog.
        /// </summary>
        /// <returns>If the user clicks the OK button of the dialog that is
        /// displayed, true is returned; otherwise, false.</returns>
        public bool? ShowDialog()
        {
            return this.Dialog.ShowDialog(this.owner);
        }

        /// <summary>
        /// Resets the properties of a common dialog to their default values.
        /// </summary>
        public void Reset()
        {
            this.Dialog.Reset();
        }
    }
}
